package model.pieces;

import java.util.List;
import model.Cell;
import model.ChessBoard;
import model.Color;
import model.File;
import model.Move;
import model.MoveFactory;
import model.exceptions.InvalidMoveException;

/**
 * Represents a chess piece.
 * This class defines the basic behavior for a chess piece and provides a basic skeleton for the concrete pieces 
 * implementation 
 * 
 * @author dmorgan
 *
 */
public abstract class Piece
{
    private Cell _position;
    private Color _color;
       
    public Cell getPosition()
    {
        return _position;
    }
    
    public void setPosition(Cell position)
    {
        _position = position;
    }

    public Color getColor()
    {
        return _color;
    }
        
    public Piece(Color color)
    {
        _color = color;
    }
    
    public Move moveTo(File file, int rank) throws InvalidMoveException
    {   
        if(!isValidMove(file, rank))
        {
            throw new InvalidMoveException();
        }
        
        return MoveFactory.createMove(this, getCellFromChessBoard(file, rank)).execute();
    }
    
    /**
     * Determines whether the chess board cell <code>file</code>,<code>rank</code> is a valid
     * destiny for the piece 
     * <p>
     * This method depends on the implementation of the <code>possibleDestinies</code> method
     * 
     * @param file a File indicating the file coordinate of the move to validate. 
     * @param rank an integer indicating the rank coordinate of the move to validate. @See {@link Rank}
     * 
     * @return true if the coordinates <code>file</code>,<code>rank</code> mark a valid destiny for the piece
     */
    public boolean isValidMove(File file, int rank)
    {
        return possibleDestinies().contains(getCellFromChessBoard(file, rank));
    }

    protected abstract List<Cell> possibleDestinies(); 
    
    protected Cell getCellFromChessBoard(File file, int rank)
    {
        return getChessBoard().getCell(file, rank);
    }
       
    protected Color getEnemyColor()
    {
        return (getColor() == Color.White) ? Color.Black : Color.White;
    }
    
    protected File getFile()
    {
        return getPosition().getFile();
    }
    
    protected int getRank()
    {
        return getPosition().getRank();
    }
    
    private ChessBoard getChessBoard()
    {
        return getPosition().getChessBoard();
    }
}
